// Package logger provides a rotating log system for the WePayKit application.
// It implements hourly log rotation and stores logs in the ./logs directory
// with filenames in the format wpk-YYYYMMDD-HH.log
package logger

import (
	"fmt"
	"os"
	"path/filepath"
	"time"
)

// Logger represents a rotating logger instance
type Logger struct {
	logDir    string
	appName   string
	currentFile *os.File
	currentHour int
}

// New creates a new Logger instance
func New(logDir, appName string) (*Logger, error) {
	// Create log directory if it doesn't exist
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("failed to create log directory: %w", err)
	}

	logger := &Logger{
		logDir:  logDir,
		appName: appName,
	}

	// Open initial log file
	if err := logger.openLogFile(); err != nil {
		return nil, fmt.Errorf("failed to open initial log file: %w", err)
	}

	return logger, nil
}

// openLogFile opens a new log file based on current time
func (l *Logger) openLogFile() error {
	// Close existing file if open
	if l.currentFile != nil {
		l.currentFile.Close()
	}

	// Get current time
	now := time.Now()
	l.currentHour = now.Hour()

	// Generate filename in format wpk-YYYYMMDD-HH.log
	filename := fmt.Sprintf("%s-%s-%02d.log", l.appName, now.Format("20060102"), l.currentHour)
	filePath := filepath.Join(l.logDir, filename)

	// Open file for writing (append if exists)
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return fmt.Errorf("failed to open log file %s: %w", filePath, err)
	}

	l.currentFile = file
	return nil
}

// checkRotation checks if log rotation is needed and performs it
func (l *Logger) checkRotation() error {
	now := time.Now()
	if now.Hour() != l.currentHour {
		return l.openLogFile()
	}
	return nil
}

// Info logs an info level message
func (l *Logger) Info(message string) error {
	return l.Log("INFO", message)
}

// Error logs an error level message
func (l *Logger) Error(message string) error {
	return l.Log("ERROR", message)
}

// Warn logs a warning level message
func (l *Logger) Warn(message string) error {
	return l.Log("WARN", message)
}

// Debug logs a debug level message
func (l *Logger) Debug(message string) error {
	return l.Log("DEBUG", message)
}

// Log writes a log message with the specified level
func (l *Logger) Log(level, message string) error {
	// Check if rotation is needed
	if err := l.checkRotation(); err != nil {
		return fmt.Errorf("failed to rotate log file: %w", err)
	}

	// Format log entry
	timestamp := time.Now().Format("2006-01-02 15:04:05")
	logEntry := fmt.Sprintf("[%s] [%s] %s\n", timestamp, level, message)

	// Write to file
	if _, err := l.currentFile.WriteString(logEntry); err != nil {
		return fmt.Errorf("failed to write log entry: %w", err)
	}

	// Flush to ensure it's written to disk
	if err := l.currentFile.Sync(); err != nil {
		return fmt.Errorf("failed to sync log file: %w", err)
	}

	return nil
}

// Close closes the current log file
func (l *Logger) Close() error {
	if l.currentFile != nil {
		return l.currentFile.Close()
	}
	return nil
}